home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d14
/
atre12.arc
/
LF.ARC
/
LF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-27
|
16KB
|
493 lines
/*****************************************************************************
**** ****
**** lf.c ****
**** ****
**** Copyright (C) A. Dwelly and W.W. Armstrong, 1990. ****
**** ****
**** All rights reserved. ****
**** ****
**** This is an experimentors package, and demonstration of the adaptive ****
**** logic network package based on work done by Prof. W. W. Armstrong ****
**** and others in the Department of Computing Science, University of ****
**** Alberta, and previous work at the Universite de Montreal, and at ****
**** AT&T Bell Laboratories, Holmdel, N. J. The software demonstrates ****
**** that networks consisting of many layers of linear threshold ****
**** elements can indeed be effectively trained. ****
**** ****
**** License: ****
**** A royalty-free license is granted for the use of this software for ****
**** NON-COMMERCIAL PURPOSES ONLY. The software may be copied and ****
**** modified provided this notice appears in its entirety and unchanged ****
**** in all copies, whether changed or not. Persons modifying the code ****
**** are requested to state the date, the changes made and who made them ****
**** in the modification history. ****
**** ****
**** Warranty: ****
**** No warranty of any kind is provided with this software. ****
**** This software is not supported. Neither the authors, nor the ****
**** University of Alberta, its officers, agents, servants or employees ****
**** shall be liable or responsible in any way for any damage to ****
**** property or direct personal or consequential injury of any nature ****
**** whatsoever that may be suffered or sustained by any licensee, user ****
**** or any other party as a consequence of the use or disposition of ****
**** this software. ****
**** ****
**** Patent: ****
**** The use of a digital circuit which transmits a signal indicating ****
**** heuristic responsibility is protected by U. S. Patent 3,934,231 ****
**** and others assigned to Dendronic Decisions Limited of Edmonton, ****
**** W. W. Armstrong, President. ****
**** ****
**** A royalty-free license is granted for the use of this patent to ****
**** run this software for NON-COMMERCIAL PURPOSES ONLY and the ****
**** extension of this patent license to modified versions of this ****
**** software is granted provided the purpose is NON-COMMERCIAL ONLY. ****
**** ****
**** Modification history: ****
**** ****
**** 90.09.05 Initial implementation, A.Dwelly ****
**** 91.04.15 Port to PC and minor bug fixes, R. Manderscheid ****
**** 91.05.20 Windows Port & Windows Extensions, M. Thomas ****
**** ****
*****************************************************************************/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <windows.h>
#include "atree.h"
#include "lf.h"
#define Printf(str,fmt1,fmt2) sprintf(szBuffer,str,fmt1,fmt2)
#define VERBOSITY 0
#define CORRECTION_FACTOR 10000
#define CODOMAIN (prog.dimensions - 1)
prog_type prog;
LPBIT_VEC domain_set;
LPBIT_VEC codomain_set;
LPATREE far * far *forest;
extern FILE *yyin;
extern int line_no;
extern bool test_size_flag;
extern bool train_size_flag;
extern bool largest_flag;
extern bool smallest_flag;
void NEAR PASCAL
prog_init()
{
atree_init();
train_size_flag = FALSE;
test_size_flag = FALSE;
largest_flag = FALSE;
smallest_flag = FALSE;
prog.vote = 1;
}
void NEAR PASCAL
read_prog(fp)
FILE *fp;
{
yyin = fp;
line_no = 1;
if (yyparse() == -1)
prog.error = TRUE;
}
BOOL NEAR PASCAL
process_prog(HWND hwnd)
{
int i;
int j;
int nv;
LPBIT_VEC far *concat;
LPBIT_VEC bool_res;
/*
* When this function is called, the program has been read in, and
* the relevant details have been stored in the global structure
* 'prog'. We have some semantic processing to do, then the trees
* can be trained as specified.
*/
/* Quantize the dimensions */
prog.width_sum = 0;
domain_set = (LPBIT_VEC) WinMem_Malloc(LMEM_MOVEABLE, (unsigned) sizeof(bit_vec) *
prog.trainset_sz);
MEMCHECK(domain_set);
codomain_set = (LPBIT_VEC) WinMem_Malloc(LMEM_MOVEABLE, (unsigned) sizeof(bit_vec) *
prog.trainset_sz);
MEMCHECK(codomain_set);
for (i = 0; i < prog.dimensions; i++)
{
if (!largest_flag)
{
prog.largest[i] = prog.train_table[i][0];
for (j = 1; j < prog.trainset_sz; j++)
{
if (prog.train_table[i][j] > prog.largest[i])
{
prog.largest[i] = prog.train_table[i][j];
}
}
for (j = 1; j < prog.testset_sz; j++)
{
if (prog.test_table[i][j] > prog.largest[i])
{
prog.largest[i] = prog.test_table[i][j];
}
}
}
if (!smallest_flag)
{
prog.smallest[i] = prog.train_table[i][0];
for (j = 1; j < prog.trainset_sz; j++)
{
if (prog.train_table[i][j] < prog.smallest[i])
{
prog.smallest[i] = prog.train_table[i][j];
}
}
for (j = 1; j < prog.testset_sz; j++)
{
if (prog.test_table[i][j] < prog.smallest[i])
{
prog.smallest[i] = prog.test_table[i][j];
}
}
}
/* Check for constant columns */
if (prog.largest[i] == prog.smallest[i])
{
char szBuffer[80];
wsprintf(szBuffer,"Semantics error: column %d of function definition is a constant",i);
MessageBox(hwnd, szBuffer, "LF ERROR", MB_OK);
return(FALSE);
}
/* Correct largest value */
if (prog.string_width[i] > 1)
{
prog.largest[i] += 1/(CORRECTION_FACTOR * prog.quant[i]);
}
/* prog.width_sum is the bit width of the domain of the function */
if (i < CODOMAIN)
{
prog.width_sum += prog.string_width[i];
}
prog.quant_step[i] = (prog.largest[i] - prog.smallest[i])/
prog.quant[i];
if (prog.string_width[i] > 1)
{
prog.random_walk[i] = atree_rand_walk(prog.quant[i] + 1,
prog.string_width[i],
prog.walk_step[i]);
}
else
{
/* one of the columns is boolean */
prog.random_walk[i] = NULL;
}
} /* for (i...) */
/*
* random_walk[i] covers the dimension i.
* we now create the training set of bit vectors.
*/
concat = (LPBIT_VEC far *) WinMem_Malloc(LMEM_MOVEABLE, (unsigned)(CODOMAIN) * sizeof(LPBIT_VEC));
MEMCHECK(concat);
for (i = 0; i < prog.trainset_sz; i++)
{
for (j = 0; j < CODOMAIN; j++)
{
if (prog.string_width[j] > 1)
{
nv = (int)floor((prog.train_table[j][i] - prog.smallest[j])/
prog.quant_step[j]);
concat[j] = prog.random_walk[j] + nv;
}
else
{
/* boolean data */
bool_res = bv_create(1);
bv_set(0,bool_res,prog.train_table[j][i] != 0);
concat[j] = bool_res;
}
}
domain_set[i] = *(bv_concat(CODOMAIN, concat));
}
/* And the codomain set */
for (i = 0; i < prog.trainset_sz; i++)
{
if (prog.string_width[CODOMAIN] > 1)
{
nv = (int) floor((prog.train_table[CODOMAIN][i] -
prog.smallest[CODOMAIN])/
prog.quant_step[CODOMAIN]);
codomain_set[i] = prog.random_walk[prog.dimensions -1][nv];
}
else
{
bool_res = bv_create(1);
bv_set(0,bool_res,prog.train_table[CODOMAIN][i] != 0);
codomain_set[i] = *bool_res;
}
}
/*
* For each tree (the number of bits in the ranges bit_string -
* create a tree and train it.
*/
forest = (LPATREE far * far *) WinMem_Malloc(LMEM_MOVEABLE, (unsigned) sizeof(LPATREE far *) *
prog.string_width[CODOMAIN]);
MEMCHECK(forest);
for (i = 0; i < prog.string_width[CODOMAIN]; i++)
{
forest[i] = (LPATREE far *) WinMem_Malloc(LMEM_MOVEABLE, (unsigned) sizeof(LPATREE) * prog.vote);
MEMCHECK(forest[i]);
}
/* parallelism here ? */
for (i = 0; i < prog.string_width[CODOMAIN]; i++)
{
for (j = 0; j < prog.vote; j++)
{
forest[i][j] = atree_create(prog.width_sum,prog.tree_sz);
(void) atree_train(forest[i][j],domain_set, codomain_set,
i, prog.trainset_sz, prog.max_correct,
prog.max_epochs, VERBOSITY);
}
}
return(TRUE);
}
void NEAR PASCAL
test_prog(HWND hwnd, LPSTR szOutFile)
{
/* Test the forest against the test set */
int i;
int j;
int k;
LPBIT_VEC result;
LPBIT_VEC far *concat;
int nv;
LPBIT_VEC test_vec;
int cl;
int closest;
int closest_bit_diff;
int weight;
LPBIT_VEC bool_res;
int hOut; /* file Handle */
char szBuffer[80];
/* Create room for the results */
result = (LPBIT_VEC )WinMem_Malloc(LMEM_MOVEABLE,(unsigned)sizeof(bit_vec)*prog.testset_sz);
MEMCHECK(result);
test_vec = (LPBIT_VEC )WinMem_Malloc(LMEM_MOVEABLE,(unsigned)sizeof(bit_vec)*prog.testset_sz);
MEMCHECK(test_vec);
for (i = 0; i < prog.testset_sz; i++)
{
result[i] = *(bv_create(prog.string_width[CODOMAIN]));
}
/* Create test set inputs */
concat = (LPBIT_VEC far *) WinMem_Malloc(LMEM_MOVEABLE,(unsigned)(CODOMAIN) *
sizeof(LPBIT_VEC ));
MEMCHECK(concat);
for (i = 0; i < prog.testset_sz; i++)
{
for (j = 0; j < CODOMAIN; j++)
{
if (prog.string_width[j] > 1)
{
nv = (int)floor((prog.test_table[j][i] - prog.smallest[j])/
prog.quant_step[j]);
prog.test_table_quant[j][i] = nv;
concat[j] = prog.random_walk[j] + nv;
}
else
{
bool_res = bv_create(1);
bv_set(0,bool_res,prog.test_table[j][i] != 0);
concat[j] = bool_res;
}
}
test_vec[i] = *(bv_concat(CODOMAIN, concat));
nv = (int)floor((prog.test_table[CODOMAIN][i] -
prog.smallest[CODOMAIN])/ prog.quant_step[CODOMAIN ]);
prog.test_table_quant[CODOMAIN][i] = nv;
}
/* Now test each tree in turn */
for (i = 0; i < prog.string_width[CODOMAIN]; i++)
{
for (j = 0; j < prog.testset_sz; j++)
{
weight = 0;
for (k = 0; k < prog.vote; k++)
{
if (atree_eval(forest[i][k], test_vec + j))
{
weight++;
}
bv_set(i,result + j, weight > (prog.vote / 2));
}
}
}
/* Now calculate the nearest vector in the codomains random walk */
/* open output file */
if ((hOut = _lcreat(szOutFile, 0)) == -1)
{
wsprintf(szBuffer,"Cannot open %s ", szOutFile);
MessageBox(hwnd, szBuffer, "LF File Error", MB_OK);
return;
}
if (prog.string_width[CODOMAIN] > 1)
{
for (i = 0; i < prog.testset_sz; i++)
{
closest_bit_diff = prog.string_width[CODOMAIN];
closest = 0;
for (j = 0; j < prog.quant[CODOMAIN]; j++)
{
if ((cl = bv_diff(result + i,prog.random_walk[CODOMAIN] + j)) < closest_bit_diff)
{
closest_bit_diff = cl;
closest = j;
}
}
for (j = 0; j < prog.dimensions; j++)
{
Printf("%f %d \t",prog.test_table[j][i],prog.test_table_quant[j][i]);
_lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
}
Printf("%f %d \r\n",(closest * prog.quant_step[CODOMAIN]) + prog.smallest[CODOMAIN],closest);
_lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
}
}
else
{
for (i = 0; i < prog.testset_sz; i++)
{
for (j = 0; j < prog.dimensions; j++)
{
Printf("%f %d \t",prog.test_table[j][i],prog.test_table_quant[j][i]);
_lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
}
Printf("%f %d \r\n",(float) bv_extract(0,result + i),bv_extract(0,result + i));
_lwrite(hOut, (LPSTR) szBuffer, lstrlen((LPSTR) szBuffer));
}
}
_lclose((int)hOut); /* close output file */
}
BOOL NEAR PASCAL
main(HWND hwnd, LPSTR szInFile, LPSTR szOutFile)
{
FILE *fp;
PSTR szFileName;
/* Initialise the default values for the program */
prog_init();
if (szInFile == NULL)
{
MessageBox(hwnd, "No Input File Specified", "LF File Error", MB_OK);
return(FALSE);
}
if (szOutFile == NULL)
{
MessageBox(hwnd, "No Output File Specified", "LF File Error", MB_OK);
return(0);
}
/* Read the input file */
lstrcpy((LPSTR)szFileName, szInFile); /* fopen needs near pointer */
if ((fp = fopen(szFileName,"r")) == NULL)
{
char szBuffer[80];
wsprintf(szBuffer,"Can't open %s ", szInFile);
MessageBox(NULL, szBuffer, "LF File Error", MB_OK);
return (FALSE);
}
else
{
read_prog(fp);
(void) fclose(fp);
}
/* Train the trees as specified if there were no syntax errors */
if (!prog.error)
{
MessageBox(hwnd, "Processing program", "LF", MB_OK);
if(!process_prog(hwnd))
{
return(FALSE);
}
}
/* Execute the trees as specified */
if (!prog.error)
{
MessageBox(hwnd, "Testing program", "LF", MB_OK);
test_prog(hwnd, szOutFile);
}
/* Finish */
return(TRUE);
}